import Glibc
class Timer {
    private let CLOCK_REALTIME = 0
    private var start_timespec = timespec()
    private var end_timespec = timespec()
    private var time_spec = timespec()
    func start() {
        clock_gettime(Int32(CLOCK_REALTIME),&start_timespec)
    }
    
    func stop() -> Double {
        clock_gettime(Int32(CLOCK_REALTIME),&end_timespec)
        let start_time = Double(start_timespec.tv_sec * 1_000_000 + start_timespec.tv_nsec / 1_000)
        let end_time = Double(end_timespec.tv_sec * 1_000_000 + end_timespec.tv_nsec / 1_000)
        let time = end_time - start_time
        return time / 1_000
    }
    func getTime() -> Double {
        clock_gettime(Int32(CLOCK_REALTIME),&time_spec)
        return Double(time_spec.tv_sec * 1_000_000 + time_spec.tv_nsec / 1_000)
    }
}
var global = 0

func GenerateFakeRandomInteger() -> [Int] {
    let resource: [Int] = [12, 43, 56, 76, 89, 54, 45, 32, 35, 47, 46, 44, 21, 37, 84]
    return resource;
}

class Example {
    // static With parameters
    @inline(never)
    static func foo(resources: [Int], i: Int, i3: Int, resourcesLength: Int) ->Int {
        var i4 = i3;
        if ((resources[i % Int(i3) & (resourcesLength - 1)] & 1) == 0) {
            i4 += 1;
        } else {
            i4 += 2;
        }
        return i4;
    }
    // static Without parameters
    @inline(never)
    static func parameterlessFoo() {
        global += 1
    }
    // static Different  parameters
    @inline(never)
    static func differentFoo(_ a: Int, _ b: String, _ c: Bool) {
        global += 1
    }
    // static Default  parameters
    @inline(never)
    static func defaultFoo(_ a: Int = 0, _ b: String = "b", _ c: Bool = true) {
        global += 1
    }
    // static Variable  parameters
    @inline(never)
    static func variableFoo(_ a: Int? = nil, _ b: String? = nil, _ c: Bool? = nil) {
        global += 1
    }
    // static ...Args  parameters
    @inline(never)
    static func argsFoo(_ args: Int...) {
        global += 1
    }
}

func runStaticFunction() -> Int {
    let count = 10000000
    let timer = Timer()
    let resources = GenerateFakeRandomInteger();
    var i3 = 1
    timer.start()
    let func1:([Int], Int, Int, Int) -> Int = Example.foo
    let resourcesLength = resources.count
    for i in 0..<count {
        i3 = func1(resources, i, i3, resourcesLength)
    }
    let time = timer.stop()
    print("Static Function Call - RunNormalCall:\t"+String(time)+"\tms");
    return Int(time)
}
_ = runStaticFunction()

func runParameterlessStaticFunction() -> Int {
    let count = 10000000
    let timer = Timer()
    global = 0
    timer.start()
    for _ in 0..<count {
        Example.parameterlessFoo()
    }
    let time = timer.stop()
    print("Static Function Call - RunParameterlessCall:\t"+String(time)+"\tms");
    return Int(time)
}
_ = runParameterlessStaticFunction()

func runNormalDifStaticFunc() -> Int {
    let count = 10000000
    let timer = Timer()
    global = 0
    timer.start()
    for _ in 0..<count {
        Example.differentFoo(1, "2", true)
    }
    let time = timer.stop()
    print("Static Function Call - RunNormalDifferentCall:\t"+String(time)+"\tms");
    return Int(time)
}
_ = runNormalDifStaticFunc()

func runNormalVariableStaticFunc() -> Int {
    let count = 10000000
    let timer = Timer()
    global = 0
    timer.start()
    for _ in 0..<count {
        Example.variableFoo(1, "2", true)
    }
    let time = timer.stop()
    print("Static Function Call - RunNormalVariableFCall:\t"+String(time)+"\tms");
    return Int(time)
}
_ = runNormalVariableStaticFunc()

func runNormalDefStaticCall() -> Int {
    let count = 10000000
    let timer = Timer()
    global = 0
    timer.start()
    for _ in 0..<count {
        Example.defaultFoo()
    }
    let time = timer.stop()
    print("Static Function Call - RunNormalDefCall:\t"+String(time)+"\tms");
    return Int(time)
}
_ = runNormalDefStaticCall()

func runNormalArgsStaticCall() -> Int {
    let count = 10000000
    let timer = Timer()
    global = 0
    timer.start()
    for _ in 0..<count {
        Example.argsFoo(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    }
    let time = timer.stop()
    print("...Args Parameter Static Normal Call:\t\(time)\tms")
    return Int(time)
}
print("Swift Method Call Is End, global value : \(global)")
